package com.homolo.msd;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.homolo.msd.util.DnsUtils;

/**
 * Detect the mail setting by config file.
 *
 * @author rory
 */
public class ConfigFileDetector implements Detector {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigFileDetector.class);

    private JSONArray configJsonArray;

    /**
     * The default constructor, load the default json config from mailconfig.json.
     */
    public ConfigFileDetector() {
        try {
            configJsonArray = new JSONArray(IOUtils.toString(getClass().getResourceAsStream("/mailconfig.json")));
        } catch (Exception e) {
            LOGGER.error("init the ConfigFileDetector error:", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public MailSettings detect(String mail) {
        String[] mxRecords = DnsUtils.getMXRecords(StringUtils.substringAfter(mail, "@"));
        if (mxRecords != null && mxRecords.length > 0) {
            JSONObject settingsJson = findSettingsJson(mxRecords);
            if (settingsJson != null) {
                return convertSettings(settingsJson);
            }
        }
        return null;
    }

    /**
     * convert json settings to MailSettings object.
     *
     * @param settingsJson the jsonObject to convert
     * @return the converted MailSettings object
     */
    private MailSettings convertSettings(JSONObject settingsJson) {
        MailSettings settings = new MailSettings();
        JSONObject popJson = settingsJson.getJSONObject("pop");
        settings.setPopServer(popJson.getString("host"), popJson.getInt("port"), popJson.getBoolean("ssl"));
        JSONObject smtpJson = settingsJson.getJSONObject("smtp");
        settings.setSmtpServer(smtpJson.getString("host"), smtpJson.getInt("port"), smtpJson.getBoolean("ssl"));
        JSONObject imapJson = settingsJson.getJSONObject("imap");
        settings.setImapServer(imapJson.getString("host"), imapJson.getInt("port"), imapJson.getBoolean("ssl"));
        return settings;
    }

    /**
     * find the settings jsonObject by the mxRecords.
     *
     * @param mxRecords the mxRecords to find.
     * @return return the settings jsonObject or null when not found.
     */
    private JSONObject findSettingsJson(String[] mxRecords) {
        JSONObject matchJson = null;
        for (String record : mxRecords) {
            for (int i = 0; i < configJsonArray.length(); i++) {
                JSONObject json = configJsonArray.getJSONObject(i);
                matchJson = checkRecordMatch(record, json);
                if (matchJson != null) {
                    return matchJson;
                }
            }
        }
        return matchJson;
    }

    /**
     * Check the record match or not.
     * 
     * @param record the record to check match
     * @param json the json config
     */
    private JSONObject checkRecordMatch(String record, JSONObject json) {
        JSONArray mxArray = json.getJSONArray("mx");
        for (int j = 0; j < mxArray.length(); j++) {
            if (StringUtils.equals(record, mxArray.getString(j))) {
                return json;
            }
        }
        return null;
    }
}
